from django.conf import settings
from django.contrib.auth import get_user_model, authenticate
from rest_framework import serializers
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_simplejwt.tokens import RefreshToken

from utils.simple_captcha.utils import validate_captcha
from .fields import PasswordField

User = get_user_model()
USERNAME_FIELD = User.USERNAME_FIELD


def get_username_field():
    try:
        username_field = get_user_model().USERNAME_FIELD
    except Exception:
        username_field = 'username'

    return username_field


class LoginSerializer(serializers.Serializer):

    def __init__(self, *args, **kwargs):
        """
        Dynamically add the USERNAME_FIELD to self.fields.
        """
        super(LoginSerializer, self).__init__(*args, **kwargs)

        self.fields[self.username_field] = serializers.CharField()
        self.fields['password'] = PasswordField(write_only=True)
        if settings.LOGIN_CAPTCHA_ON:
            self.fields['captcha_key'] = serializers.CharField(required=True, allow_blank=False)
            self.fields['captcha_value'] = serializers.CharField(required=True, allow_blank=False)

    @property
    def username_field(self):
        return get_username_field()

    def validate(self, attrs):
        # 验证码验证
        if settings.LOGIN_CAPTCHA_ON:
            captcha_data = {
                'captcha_key': attrs.get('captcha_key', None),
                'captcha_value': attrs.get('captcha_value', None)
            }
            if not all(captcha_data.values()):
                raise AuthenticationFailed('必须包含 "captcha_key" 和 "captcha_value" 字段')
            if not validate_captcha(attrs['captcha_key'], attrs['captcha_value']):
                raise AuthenticationFailed('验证码输入有误')

        # 登陆凭证验证
        credentials = {
            self.username_field: attrs.get(self.username_field),
            'password': attrs.get('password')
        }
        if not all(credentials.values()):
            raise AuthenticationFailed('必须包含 "{username_field}" 和 "password" 字段'.format(username_field=self.username_field))
        user = authenticate(**credentials)
        if not user:
            raise AuthenticationFailed('用户名或密码不正确')
        if not user.is_active:
            raise AuthenticationFailed('用户帐户已禁用')
        else:
            refresh = RefreshToken.for_user(user)
            data = {
                'access_token': str(refresh.access_token),
                'refresh_token': str(refresh),
                'user': user
            }
            return data


class LogoutSerializer(serializers.Serializer):
    refresh_token = serializers.CharField(required=True)